package net.lovesrc.allin.biz.treex;

import com.alibaba.fastjson.JSONObject;
import com.zhouzhou.fastjava.BizException;
import com.zhouzhou.fastjava.http.MyHttpRequest;
import com.zhouzhou.fastjava.http.Requests;
import net.lovesrc.allin.biz.BaseService;
import net.lovesrc.allin.biz.idcard.IdCardService;
import net.lovesrc.support.service.dama.DaMaService;
import net.lovesrc.support.service.imageverifycode.ImageVerifyCodeService;
import net.lovesrc.support.service.mobileverifycode.MobileVerifyCodeService;
import net.lovesrc.support.service.mobileverifycode.MobileVerifyCodeWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.cookie.ClientCookie;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

class BaseTreexService extends BaseService {

    @Autowired
    private MobileVerifyCodeService mobileVerifyCodeService;

    @Autowired
    protected IdCardService idCardService;

    @Autowired
    protected ImageVerifyCodeService imageVerifyCodeService;

    @Autowired
    protected DaMaService daMaService;

    protected MobileVerifyCodeWrapper getMobileVerifyCodeWrapper() {
        return new MobileVerifyCodeWrapper(mobileVerifyCodeService, "46224");
    }

    protected boolean isMyMobile(String mobile) {
        return jdbcTemplate.queryForObject("select count(1) from v_treex_my_account where mobile = ?", int.class, mobile) > 0;
    }

    protected boolean isNotMyMobile(String mobile) {
        return !isMyMobile(mobile);
    }

    protected boolean isOkResJson(JSONObject resJson) {
        int code = resJson.getIntValue("code");
        return code == 200;
    }

    protected void checkResJson(JSONObject resJson) {
        if (isOkResJson(resJson)) {
            // is okay
        } else {
            throw BizException.messageOf(resJson.getString("msg"));
        }
    }

    protected UserSessionMeta ensureLogin(JSONObject row) {
        String mobile = row.getString("mobile");
        String cookies = row.getString("cookies");
        CookieStore cookieStore = Requests.toCookieStore(cookies);
        if (StringUtils.isNotBlank(cookies)) {
            HttpClient httpClient = newHttpClientWithMyProxy(mobile, cookieStore);
            JSONObject userJson = getUserJson(httpClient, mobile);
            if (isOkResJson(userJson)) {
                JSONObject userJsonData = userJson.getJSONObject("data");
                return new UserSessionMeta(httpClient, userJsonData);
            }
        }
        return doLogin(row, mobile);
    }

    public JSONObject getUserJson(HttpClient httpClient, String mobile) {
        JSONObject userJson = MyHttpRequest.get(httpClient, "https://www.gdpro.pro/api/v1/session?" + System.currentTimeMillis())
                .executeUtilReturn200()
                .asJson();
        jdbcTemplate.update("update t_treex_account set accessTime = ? where mobile = ?", new Date(), mobile);
        if (isOkResJson(userJson)) {
            checkIdStatus(mobile, userJson.getJSONObject("data"));
        }
        return userJson;
    }

    public void setLoginDevice(String mobile, JSONObject row, CookieStore cookieStore) {
        if (StringUtils.isBlank(row.getString("loginDevice"))) {
            List<Cookie> cookies = cookieStore.getCookies();
            for (Cookie cookie : cookies) {
                if ("login_device".equals(cookie.getName())) {
                    jdbcTemplate.update("update t_treex_account set loginDevice = ? where mobile = ?",
                            cookie.getValue(), mobile
                    );
                    break;
                }
            }
        }
    }

    protected boolean checkIdStatus(String mobile, JSONObject userJsonData) {
        if (userJsonData.getBooleanValue("authDeep")) {
            jdbcTemplate.update("update t_treex_account set idStatus = 'success', idSuccessTime = ? where mobile = ? and idStatus <> 'success'", new Date(), mobile);
            return true;
        }
        return false;
    }

    protected BasicClientCookie newCookie(String name, String value) {
        BasicClientCookie cookie = new BasicClientCookie(name, value);
        cookie.setDomain("www.gdpro.pro");
        cookie.setExpiryDate(DateUtils.addYears(new Date(), 1));
        cookie.setPath("/");
        cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true");
        return cookie;
    }

    private synchronized UserSessionMeta doLogin(JSONObject row, String mobile) {
        CookieStore cookieStore = new BasicCookieStore();
        String loginDevice = row.getString("loginDevice");
        if (StringUtils.isNotBlank(loginDevice)) {
            cookieStore.addCookie(newCookie("login_device", loginDevice));
        }
        HttpClient httpClient = newHttpClientWithMyProxy(mobile, cookieStore);
        MyHttpRequest.get(httpClient, "https://www.gdpro.pro/user/login")
                .executeUtilReturn200();
        MyHttpRequest.get(httpClient, "https://www.gdpro.pro/api/v1/session?" + System.currentTimeMillis())
                .executeUtilReturn200();
        JSONObject resJson = MyHttpRequest.post(httpClient, "https://www.gdpro.pro/api/v1/login")
                .param("name", mobile)
                .param("pwd", row.getString("password"))
                .executeUtilReturn200()
                .asJson();
        int code = resJson.getIntValue("code");
        if (code == 200) {
            // is okay
        } else if (code == 7) {
            throw BizException.messageOf("{} 需要验证码，才能重新登录", mobile);
            /*
            String verifyCode;
            try {
                getMobileVerifyCodeWrapper().getPhone(mobile);
                MyHttpRequest.post(httpClient, "https://www.gdpro.pro/api/v1/sendLoginCode")
                        .execute()
                        .asJson();
                verifyCode = getMobileVerifyCodeWrapper().getVerifyCodeFromPhone(mobile);
            } catch (Exception e) {
                jdbcTemplate.update("update t_treex_account set isMyAccount = 99, mark = ? where mobile = ?", e.getMessage(), mobile);
                throw e;
            }
            MyHttpRequest.post(httpClient, "https://www.gdpro.pro/api/v1/secLogin")
                    .param("code", verifyCode)
                    .executeUtilReturn200()
                    .asJson();
             */
        } else {
            throw BizException.messageOf(resJson.getString("msg"));
        }

        JSONObject userJson = getUserJson(httpClient, mobile);
        checkResJson(userJson);

        setLoginDevice(mobile, row, cookieStore);

        JSONObject userJsonData = userJson.getJSONObject("data");

        JSONObject sets = new JSONObject()
                .fluentPut("userId", userJsonData.getString("id"))
                .fluentPut("inviteCode", userJsonData.getString("id"))
                .fluentPut("cookies", Requests.toCookieString(cookieStore));
        updateRow(jdbcTemplate, "t_treex_account", sets, "mobile = ?", mobile);
        return new UserSessionMeta(httpClient, userJsonData);
    }

    public boolean isNotJyTime() {
        return !isJyTime();
    }

    public boolean isJyTime() {
        String jyTime = tryGetProperties(String.class, "10-19", "Stl_Jy_Time");
        int minJyTime = Integer.valueOf(jyTime.split("-")[0]);
        int maxJyTime = Integer.valueOf(jyTime.split("-")[1]);
        int nowTime = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        return nowTime >= minJyTime && nowTime < maxJyTime;
    }

}
